package logic

import (
	"context"
	"encoding/json"
	"github.com/go-redsync/redsync/v4"
	"github.com/go-redsync/redsync/v4/redis/goredis/v9"
	"github.com/olivere/elastic/v7"
	"month_zg5/book_srv/common/global"
	"month_zg5/book_srv/models"
	book_rpc "month_zg5/book_srv/proto"
	"month_zg5/book_srv/service/es"
	"month_zg5/book_srv/service/mysql"
	"month_zg5/book_srv/service/redis"
)

// 倒叙排序
func (b *BookRpc) GetBookDesc(ctx context.Context, in *book_rpc.GetBookDescReq) (*book_rpc.GetBookDescRes, error) {
	book, err := mysql.GetBookDescByReadings()
	if err != nil {
		return &book_rpc.GetBookDescRes{}, err
	}
	var bookInfo []*book_rpc.BookInfo
	for _, v := range book {
		var info = &book_rpc.BookInfo{
			Title:            v.Title,
			BookType:         int32(v.BookType),
			Author:           v.Author,
			Content:          v.Content,
			NumberOfComments: int32(v.NumberOfComments),
			Readings:         int32(v.Readings),
		}
		bookInfo = append(bookInfo, info)
	}
	return &book_rpc.GetBookDescRes{
		Data: bookInfo,
	}, nil
}

// 高亮搜索
func (b *BookRpc) SearchBook(ctx context.Context, in *book_rpc.SearchBookReq) (*book_rpc.SearchBookRes, error) {
	query := elastic.NewMultiMatchQuery(in.Content, "title", "author", "content")
	high := elastic.NewHighlight().Fields(
		elastic.NewHighlighterField("title").PreTags("<span style='color:red'>").PostTags("<span>"),
		elastic.NewHighlighterField("author").PreTags("<span style='color:red'>").PostTags("<span>"),
		elastic.NewHighlighterField("content").PreTags("<span style='color:red'>").PostTags("<span>"),
	)
	info := es.SearchBook(in.Index, query, high)
	//添加搜索记录
	key := "es_book:"
	err := redis.BookIncr(key)
	if err != nil {
		return nil, err
	}
	return &book_rpc.SearchBookRes{
		Data: info,
	}, nil
}

// 添加到书架
func (b *BookRpc) BookShelf(ctx context.Context, in *book_rpc.BookShelfReq) (*book_rpc.BookShelfRes, error) {
	err := mysql.CreateBookShelf(&models.BookShelf{
		UserId: uint(in.Userid),
		BookId: uint(in.BookId),
	})
	if err != nil {
		return nil, err
	}
	return &book_rpc.BookShelfRes{}, nil
}

// 无限极分类
func (b *BookRpc) BookType(ctx context.Context, in *book_rpc.BookTypeReq) (*book_rpc.BookTypeRes, error) {
	data, err := mysql.GetBookType(1)
	if err != nil {
		return nil, err
	}
	return &book_rpc.BookTypeRes{Data: data}, nil
}

// 文章详情
func (b *BookRpc) GetBookDetail(ctx context.Context, in *book_rpc.GetBookDetailReq) (*book_rpc.GetBookDetailRes, error) {
	book, err := mysql.GetBookDetail(uint(in.BookId))
	if err != nil {
		return nil, err
	}
	return &book_rpc.GetBookDetailRes{Data: book}, nil
}

// redis排行榜
func (b *BookRpc) BookTop(ctx context.Context, in *book_rpc.BookTopReq) (*book_rpc.BookTopRes, error) {
	var (
		info []*book_rpc.BookInfo
		key  = "book_top:"
	)
	is := redis.IsKey(key)
	if is == 0 {
		book, err := mysql.GetBookAll()
		if err != nil {
			return nil, err
		}
		for _, v := range book {
			err = redis.CreateBook(key, v)
			if err != nil {
				return nil, err
			}
			var data = &book_rpc.BookInfo{
				Title:            v.Title,
				BookType:         int32(v.BookType),
				Author:           v.Author,
				Content:          v.Content,
				NumberOfComments: int32(v.NumberOfComments),
				Readings:         int32(v.Readings),
			}
			info = append(info, data)
		}
		return &book_rpc.BookTopRes{Data: info}, nil
	}
	data := redis.GetBook(key)
	for _, v := range data {
		var data *models.Book
		json.Unmarshal([]byte(v), &data)
		var topData = &book_rpc.BookInfo{
			Title:            data.Title,
			BookType:         int32(data.BookType),
			Author:           data.Author,
			Content:          data.Content,
			NumberOfComments: int32(data.NumberOfComments),
			Readings:         int32(data.Readings),
		}
		info = append(info, topData)
	}
	return &book_rpc.BookTopRes{Data: info}, nil
}

// 添加评论
func (b *BookRpc) CreateCommon(ctx context.Context, in *book_rpc.CreateCommonReq) (*book_rpc.CreateCommonRes, error) {
	//redis分布式锁
	pool := goredis.NewPool(global.RedisClient)
	rs := redsync.New(pool)
	mutexname := "my-global-mutex"
	mutex := rs.NewMutex(mutexname)
	//上锁
	if err := mutex.Lock(); err != nil {
		panic(err)
	}
	//解锁
	defer func() {
		if ok, err := mutex.Unlock(); !ok || err != nil {
			panic("unlock failed")
		}
	}()
	//添加评论
	err := mysql.AddComment(&models.Common{
		UserId:  uint(in.UserId),
		BookId:  uint(in.BookId),
		Content: in.Content,
		Pid:     int(in.Pid),
	})
	if err != nil {
		return nil, err
	}
	//修改评论量
	book, err := mysql.SaveBook(uint(in.BookId))
	if err != nil {
		return nil, err
	}
	return &book_rpc.CreateCommonRes{Data: int32(book.NumberOfComments)}, nil
}
